import { TimerProxy } from './dataSync/timerProxy';

/**
 * 同步锁对象
 * 
 * @class SyncObjectLocker
 */
class SyncObjectLocker {
    methodName: any;
    static Current: SyncObjectLocker = new SyncObjectLocker();
    private timer: TimerProxy;
    private methodList: { methodName: string; target: any; args: any; method: Function; callback: any }[] = [];
    private onCallResult;

    constructor() {
        this.timer = new TimerProxy(this.Call, this);
    }

    async Call() {
        this.timer.ClearTimer();

        if (this.methodList.length > 0) {
            console.log("xxxxxxxxxxxxxxxxxxxxxxxxx", new Date());
            let item = this.methodList[0];
            this.methodList.splice(0, 1);

            try {
                let result = await item.method.apply(item.target, item.args);
                console.log("cccccccccccccccccc", new Date());
                item.callback && item.callback(null, result);
            } catch (error) {
                console.log("eeeeeeeeeeeeeeeeeeeeeee", new Date());
                item.callback && item.callback(error, null);
            }
            finally {
                this.timer.SetTimer(20);
            }
        }
        else {
            this.timer.StopTimer();
        }
    }

    Lock(methodName: string, target, args, method: Function, callback) {
        this.methodList.push({
            methodName: methodName,
            target: target,
            args: args,
            method: method,
            callback: callback
        });
        this.timer.StartTimer(20);
    }
}

/**
 * 同步锁
 * 
 * @export
 * @returns 
 */
export function SyncLock() {
    return (target: any, propertyName: string, descriptor: TypedPropertyDescriptor<Function>) => {
        let method = descriptor.value;
        descriptor.value = function () {
            return new Promise((resolve, reject) => {
                SyncObjectLocker.Current.Lock(propertyName, this, arguments, method, function (err, result) {
                    console.log("rrrrrrrrrrrrrrrrrrrrrrrrrr", err);
                    if (err) reject(err);
                    else {
                        resolve(result);
                    }
                });
            });
        }
    }
}